<?php

namespace App\Console\Commands;

use App\Caches\Game\ConfigPropCache;
use App\Models\Game\Center\Account;
use App\Models\Game\Center\AccountDayStat;
use App\Models\Game\Center\AccountFlagLog;
use App\Models\Game\Center\AccountOperateLog;
use App\Models\Game\Center\AccountProfit;
use App\Models\Game\Center\AppSource;
use App\Models\Game\Center\BrokenChild;
use App\Models\Game\Center\PayOrder;
use App\Models\Game\Center\SourceLtv;
use App\Models\Game\Center\WithdrawOrder;
use App\Models\Mongo\DailyLog\DayCpaCost;
use App\Models\Mongo\DailyLog\DayStat;
use App\Models\Mongo\DailyLog\MonthStat;
use App\Models\Mongo\PlayerCache\BuildRecord;
use App\Services\GameNotifyService;
use App\Services\PayService;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Yansongda\Pay\Exceptions\GatewayException;

class Debug extends Command
{
    protected $signature = 'debug';

    protected $description = '测试代码';

    public function __construct()
    {
        parent::__construct();
    }

    public function handle()
    {
        for ($i = 1; $i <= 11; $i++) {
            $day = '2025-03-'.sprintf('%02d', $i);
            $this->info("正在更新 {$day}");
            // Artisan::call(CalcThirdTaskUserLog::class);
            Artisan::call(CalcThirdTaskConfigStat::class, [
                '--day' => $day,
            ]);
            Artisan::call(CalcThirdTaskIssueStat::class, [
                '--day' => $day,
            ]);
            sleep(1);
        }
    }

    public function syncBlackList()
    {
        dd("success");
        $svc = new \App\Services\BlackRemoteRepoService();
        $blackList = \App\Models\Game\Center\AccountBlackList::get();
        $accountList = \App\Models\Game\Center\Account::query()
            ->whereIn('userId', $blackList->pluck('user_id'))
            ->get()->keyBy('userId');
        $data = [];
        foreach ($blackList as $black) {
           $result = $svc->add($accountList[$black->user_id], $black->remark, $black->manager_name);
           $this->info("userid:{$black->user_id} result:{$result}");
        }
    }

    public function promoMigrate($class)
    {
        dd(str_replace('\Promo', '', $class));
        $originObj = new $class();
        $objClass = new \ReflectionClass($class);
        $allConsts = $objClass->getConstants();
        $all = [];
        foreach ($allConsts as $key => $val) {
            if (!Str::startsWith($key, 'KEY_')) continue;
            $originObj->set($val, mt_rand(1000, 9999), now()->addMinutes(mt_rand(0, 10)));
            $all[$key] = $originObj->get($val);
        }
        dd($all);
    }

    public function baiduDebug()
    {
        $account = Account::where('playerId', 1048577)->first();
        $account = $account->getRawOriginal();
        $account['ip'] = ip2long('101.82.245.91');
        $account['uuid']= '2bae616184eb008c99fc0448586670d6';
        $account['oaid'] = '2bae616184eb008c99fc0448586670d6';

        GameNotifyService::commandEvent('uuidActionActive', [], $account);
        sleep(1);
        GameNotifyService::commandEvent('uuidActionRegister', [], $account);
        sleep(2);
        GameNotifyService::commandEvent('uuidActionPay', [], array_merge($account, ['price' => 100]));
        sleep(2);
        GameNotifyService::commandEvent('uuidActionDelete', [], $account);
    }

    public function fixCpaCost()
    {
        $source = [2108, 2111, 2112, 2113, 2114, 2115,];
        $startDay = Carbon::parse('2023-06-20');
        $endDay = Carbon::parse('2023-07-12');
        $dayStats = DayStat::whereIn('source', $source)->whereBetween('day', [$startDay->toDateString(), $endDay->toDateString()])->get()->groupBy('day');
        foreach ($dayStats as $day => $list) {
            foreach ($list as $dayStat) {
                // 没有充值和权益不管
                if (!$dayStat->pay && !$dayStat->withdraw) continue;
                $cpaCost = ($dayStat->pay - $dayStat->withdraw) * 0.7;
                if ($cpaCost <= 0) $cpaCost = 100;

                // 更新日报表
                $dayStat->cpaCost = $cpaCost;
                $dayStat->cpaCostFormula = '(充值-权益)*0.7';
                $dayStat->cpaCostFormula = null;
                $dayStat->save();

                // 更新sourceLTV表
                SourceLtv::where('day', $day)->where('source', $dayStat->source)->update(['cpaCost' => $cpaCost]);

                $this->info("{$day}: {$dayStat->source}: old: {$dayStat->cpaCost} : new: {$cpaCost}");
            }
            sleep(1);

            // 更新渠道0数据
            $cpaCost = DayStat::where('day', $day)->where('source', '>', 0)->sum('cpaCost');
            DayStat::where('day', $day)->where('source', 0)->update(['cpaCost' => $cpaCost]);

            SourceLtv::where('day', $day)->where('source', 0)->update(['cpaCost' => $cpaCost]);
        }
    }

    public function fixBrokenChild()
    {
        $str = '1697480
1697481
1697482
1697483
1697484
1697485
1697486
1697487
1697488
1697489
1697498
1697499
1697500
1697501
1697502
1697503
1697504
1697505
1697506
1697507';
        $arr = explode("\n", $str);
        $playerIds = [];
        foreach ($arr as $id) {
            // $this->info(($id + 1048476).'    -     '.($id + Account::PLAYERID_INIT));
            $oldId = $id + 1048476;
            $newId = $id + Account::PLAYERID_INIT;
            $playerIds[$oldId] = $newId;
            // $this->info($id + Account::PLAYERID_INIT);
        }
        // dd($playerIds);
        $childs = BrokenChild::get();
        foreach ($childs as $child) {
            $oldPlayerId = $child->playerId;
            $newPlayerId = $playerIds[$oldPlayerId];

            // 更新账号日统计 07-06之前
            AccountDayStat::where('player_id', $oldPlayerId)
                ->where('day', '<', '2023-07-06')
                ->update([
                    'player_id' => $newPlayerId,
                ]);
            // 更新订单
            DB::connection('gameCenter')
                ->table((new PayOrder())->getTable())
                ->where('player_id', $oldPlayerId)
                ->where('created_at', '<', '2023-07-06 23:00:00')
                ->update([
                    'player_id' => $newPlayerId,
                ]);

            // 创建accountProfit表
            AccountProfit::firstOrCreate([
                'playerId' => $newPlayerId,
            ], [
                'userId' => $child->userId,
                'source' => $child->account->source ?? 100,
                'sum_pay' => $child->sum_pay,
                'created_at' => $child->account->created_at,
            ]);

            // 更新玩家ID
            $child->playerId = $newPlayerId;
            $child->save();

            $child->account()->where('playerId', 0)->update(['playerId' => $newPlayerId]);
            // $child->account->playerId = $newPlayerId;
            // $child->account->save();
            $this->info("{$oldPlayerId} => {$newPlayerId}");
        }

        // $this->syncOperateLog();
        // $this->fixMonthWithdraw('2023-04');
    }

    /**
     * 同步旧标签日志表
     * @return void
     */
    public function syncOperateLog()
    {
        AccountFlagLog::orderBy('id', 'asc')->chunk(1000, function($accountFlagLogs) {
            $inserts = [];
            foreach ($accountFlagLogs as $accountFlagLog) {
                /**
                 * @var AccountFlagLog $accountFlagLog
                 */
                $v['userId'] = $accountFlagLog->userId;
                $v['action'] = 'addFlag';
                if (strpos($accountFlagLog->remark, '删除') !== false) {
                    $v['action'] = 'removeFlag';
                }
                $data = __("user.flagBit.{$accountFlagLog->flag}");
                $v['data'] = $data;
                $v['remark'] = $accountFlagLog->remark;
                $v['manager_id'] = $accountFlagLog->manager_id;
                $v['manager_name'] = $accountFlagLog->manager_name;
                $v['created_at'] = $accountFlagLog->created_at;
                $v['updated_at'] = $accountFlagLog->updated_at;
                $inserts[] = $v;
            }
            AccountOperateLog::insert($inserts);
        });
    }
    public function fixMonthSpreadUser()
    {
        $dayStats = DayStat::where('source', '>', 0)
            ->where('day', '>=', '2023-03-01')
            ->where('day', '<', '2023-06-01')
            ->where('spreadUser', '!=', '')
            ->get();

        $users = [];
        $types = [];
        $channels = [];
        foreach ($dayStats as $dayStat) {
            $month = substr($dayStat->day, 0, strrpos($dayStat->day, '-'));
            if (empty($users[$month])) $users[$month] = [];
            if (empty($users[$month][$dayStat->source])) $users[$month][$dayStat->source] = [];

            // if (empty($types[$month])) $types[$month] = [];
            // if (empty($types[$month][$dayStat->source])) $types[$month][$dayStat->source] = [];
            //
            // if (empty($channels[$month])) $channels[$month] = [];
            // if (empty($channels[$month][$dayStat->source])) $channels[$month][$dayStat->source] = [];

            $users[$month][$dayStat->source][] = $dayStat->spreadUser;
            // $types[$month][$dayStat->source][] = $dayStat->spreadType;
            // $channels[$month][$dayStat->source][] = $dayStat->spreadChannel;
        }
        foreach ($users as $month => $lists) {
            foreach ($lists as $source => $list) {
                $users[$month][$source] = array_unique($list);
            }
        }
        // dd($users);
        foreach ($users as $month => $lists) {
            foreach ($lists as $source => $list) {
                $users[$month][$source] = $list[0];
            }
        }
        // dd($users);
        foreach ($users as $month => $lists) {
            foreach ($lists as $source => $user) {
                $monthStat = MonthStat::where('month', $month)->where('source', $source)->first();
                $monthStat->spreadUser = $user;
                $this->info("渠道 {$monthStat->month} {$monthStat->source}: {$monthStat->getOriginal('spreadUser')} -> {$user}");
                $monthStat->save();
            }
        }
        // foreach ($types as $month => $lists) {
        //     foreach ($lists as $source => $list) {
        //         $types[$month][$source] = array_unique($list);
        //     }
        // }
        // dd($types);
        // foreach ($channels as $month => $lists) {
        //     foreach ($lists as $source => $list) {
        //         $channels[$month][$source] = array_unique($list);
        //     }
        // }
        // dd($channels);
    }

    public function fixWithdrawChannelFee()
    {
        // withdrawChannelFee
        // $dayStats = DayStat::whereBetween('day', ['2023-03-01', '2023-03-31'])->get();
        // foreach ($dayStats as $dayStat) {
        //     if (!$dayStat->withdrawChannelFee) continue;
        //     $this->info("{$dayStat->day} {$dayStat->source} 原通道费: {$dayStat->withdrawChannelFee}, 新通道费: ". ($dayStat->withdrawChannelFee/0.09*0.03));
        //     $dayStat->withdrawChannelFee = $dayStat->withdrawChannelFee/0.09*0.03;
        //     $dayStat->save();
        // }
        $month = '2023-03';
        $monthStats = MonthStat::where('month', $month)->get();
        foreach ($monthStats as $monthStat) {
            if (!$monthStat->withdrawChannelFee) continue;
            $this->info("{$month} {$monthStat->source} 原通道费: {$monthStat->withdrawChannelFee}, 新通道费: ". ($monthStat->withdrawChannelFee/0.09*0.03));

            $monthStat->withdrawChannelFee = $monthStat->withdrawChannelFee/0.09*0.03;
            $monthStat->save();
        }

    }

    public function fixMonthWithdraw(string $month)
    {
        $appSources = AppSource::get();
        $sources = array_column($appSources->toArray(), 'id');
        $sources = array_merge([0], $sources);
        foreach ($sources as $source) {
            $withdraw = DayStat::where('source', $source)->whereBetween('day', ["{$month}-01", "{$month}-31"])->sum('withdraw');
            $monthStat = MonthStat::where('source', $source)->where('month', $month)->first();

            if (!$monthStat) continue;
            $this->info("{$month} 渠道: {$source}");

            if ($monthStat->withdraw != $withdraw) {
                $this->info("渠道: {$source}, 日汇总: {$withdraw}, 月表: {$monthStat->withdraw}, 差额:". ($monthStat->withdraw - $withdraw));
                $monthStat->withdraw = $withdraw;
                $monthStat->save();
            }
        }
    }

    /**
     * 修正指定日期的兑换数据
     * @return void
     */
    public function fixDayWithdraw()
    {
        $appSources = AppSource::get();
        $dayStart = Carbon::parse('2023-03-01');
        $dayEnd = Carbon::parse('2023-04-30');
        $diffDay = $dayEnd->diffInDays($dayStart);

        $calcDayStat = new CalcDayStat();
        $days = ['2023-03-23', '2023-04-07', '2023-04-08'];
        // for ($i = 0; $i <= $diffDay; $i++) {
        //     $day = $dayStart->copy()->addDays($i);
        foreach ($days as $day) {
            $day = Carbon::parse($day);
            $calcDayStat->setDay($day);
            $withdrawSums = $calcDayStat->getWithdrawSum();

            $dayStatAll = DayStat::firstOrNew(['day' => $day->toDateString(), 'source' => 0]);
            $dayStatAll->withdraw =0;
            $dayStatAll->withdrawUser =0;
            $dayStatAll->withdrawCash =0;
            $dayStatAll->withdrawJd =0;
            $dayStatAll->withdrawChannelFee =0;
            foreach ($appSources as $appSource) {
                $dayStat = DayStat::firstOrNew(['day' => $day->toDateString(), 'source' => $appSource->id]);
                $oldWithdraw = $dayStat->withdraw;
                list($dayStat->withdraw, $dayStat->withdrawUser, $dayStat->withdrawCash, $dayStat->withdrawJd, $dayStat->withdrawChannelFee) = $withdrawSums[$appSource->id] ?? [0,0,0,0,0]; // 今日权益金额和人数

                $dayStatAll->withdraw += $dayStat->withdraw;
                $dayStatAll->withdrawUser += $dayStat->withdrawUser;
                $dayStatAll->withdrawCash += $dayStat->withdrawCash;
                $dayStatAll->withdrawJd += $dayStat->withdrawJd;
                $dayStatAll->withdrawChannelFee += $dayStat->withdrawChannelFee;

                if ($oldWithdraw != $dayStat->withdraw) {
                    $this->info("{$dayStat->day}, {$dayStat->source}, {$oldWithdraw}, {$dayStat->withdraw}, {$dayStat->withdrawUser}");
                    $dayStat->save();
                    SourceLtv::where('day', $dayStat->day)->where('source', $dayStat->source)->update([
                        'withdraw' => $dayStat->withdraw,
                        'withdrawUser' => $dayStat->withdrawUser,
                    ]);
                }
            }

            // 更新source = 0数据
            if ($dayStatAll->isDirty()) {
                $this->info("ALL {$dayStatAll->day}, {$dayStatAll->source}, {$dayStatAll->getOriginal('withdraw')}, {$dayStatAll->withdraw}, {$dayStatAll->withdrawUser}");
                $dayStatAll->save();
                SourceLtv::where('day', $dayStat->day)->where('source', 0)->update([
                    'withdraw' => $dayStatAll->withdraw,
                    'withdrawUser' => $dayStatAll->withdrawUser,
                ]);
            }
        }
    }

    /**
     * 修正老的兑换订单
     * @return void
     */
    public function fixOldWithdraw()
    {
        $orders = WithdrawOrder::whereBetween('created_at', ['2023-03-01 00:00:00', '2023-04-31 23:59:59'])
            ->where('status', WithdrawOrder::STATUS_FAILED)
            ->where('reason', '系统繁忙')
            ->get();
        foreach ($orders as $withdrawOrder) {
            $withdrawOrder->pay_channel_id = 37;
            $channel = $withdrawOrder->channel;
            if (!in_array($channel, ['alipay', 'wechat'])) continue;
            $this->info($withdrawOrder->id);

            continue;
            try {
                $payProvider = PayService::alipay();
                list($status, $reason, $torderid) = $payProvider->withdrawOrderQuery($withdrawOrder);
            } catch (\Exception $e) {
                report($e);
                continue;
            }
            if ($status === WithdrawOrder::STATUS_FAILED) {
                info(__METHOD__, [$withdrawOrder->id, '检查权益订单, 该订单支付失败']);
                GameNotifyService::withdrawOrderUpdate($withdrawOrder->id, $status);
            } else if ($status === WithdrawOrder::STATUS_SUCCESS) {
                info(__METHOD__, [$withdrawOrder->id, '检查权益订单, 确认该订单已完成']);
            }

            // 不更新时间
            $withdrawOrder->timestamps = false;
            $withdrawOrder->status = $status;
            if ($withdrawOrder->torderid) $withdrawOrder->torderid = $torderid;
            if ($reason) $withdrawOrder->reason = "重试订单 {$reason}";
            $withdrawOrder->save();
        }
    }

    /**
     * 检查推广费
     * @return void
     */
    public function checkCpaCost()
    {
        for ($i = 1; $i <= 28; $i++) {
            $day = sprintf("2023-05-%02d", $i);
            $costs = $this->getCpaCost($day);

            // 自动查询的推广费与日报表中不匹配
            $dayStats = DayStat::where('source', '>', 0)->where('day', $day)->get();
            foreach ($dayStats as $dayStat) {
                $cost = $costs[$dayStat->source] ?? 0;
                if ($cost != $dayStat->cpaCost) {
                    $this->info(sprintf("日期: {$day}, 渠道: {$dayStat->source}, 花费: %d, 实际: %d", $dayStat->cpaCost, $cost));
                }
            }
            // 渠道0的推广费
            $totalCpaCost = DayStat::where('source', '>', 0)->where('day', $day)->sum('cpaCost');
            $actualCpaCost = DayStat::where('source', 0)->where('day', $day)->value('cpaCost');
            if ($totalCpaCost != $actualCpaCost) {
                $this->info(sprintf("日期: {$day}, 花费: %d, 实际: %d", $totalCpaCost, $actualCpaCost));
            }
        }
    }

    /**
     * 日报表
     * 修复各个渠道花费的推广费
     * 先运行 sync:source-cpa-cost
     * @param string $day
     * @return void
     */
    public function fixDayStatCpaCost(string $day)
    {
        // 修正各个渠道数据
        $costs = $this->getCpaCost($day);
        foreach ($costs as $source => $cpaCost) {
            DayStat::where('source', $source)->where('day', $day)->update([
                'cpaCost' =>$cpaCost,
            ]);
        }
        // 修复渠道O的数据
        $cpaCost = DayStat::where('source', '>', 0)->where('day', $day)->sum('cpaCost');
        DayStat::where('source', 0)->where('day', $day)->update([
            'cpaCost' => $cpaCost,
        ]);
        $this->fixSourceLtvCost($day);
    }

    /**
     * SourceLtv表
     * 同步各个渠道推广费
     * @param string $day
     * @return void
     */
    public function fixSourceLtvCost(string $day)
    {
        // 修正各个渠道数据
        $costs = $this->getCpaCost($day);
        foreach ($costs as $source => $cpaCost) {
            SourceLtv::where('source', $source)->where('day', $day)->update([
                'cpaCost' =>$cpaCost,
            ]);
        }
        // 修复渠道O的数据
        $cpaCost = SourceLtv::where('source', '>', 0)->where('day', $day)->sum('cpaCost');
        SourceLtv::where('source', 0)->where('day', $day)->update([
            'cpaCost' => $cpaCost,
        ]);
    }

    /**
     * 获取CPA花费 四舍五入取整
     * @param string $day
     * @return array
     */
    public function getCpaCost(string $day): array
    {
        $dayCpaCost = new DayCpaCost();
        $cpaCosts = $dayCpaCost->getCpaCostActuals([$day, $day]);
        return array_map(function ($v) {
            $v /= 100;
            return round($v) * 100;
        }, $cpaCosts);
    }

}
